/*
 * fixedtreenode.h
 *
 *  Created on: Mar 29, 2011
 *      Author: Mo
 */
#pragma once

#include "rulebase.h"


/**
 * Tells the decision the node makes, if any.
 * All the nodes are initialized in nodeDecision = blank; and when the child of a parent  receives a non-empty rule base,
 * it updates its decision.
 */
enum decision
{
	dwhite,
	dblack,
	dnotYet,
	dblank
};

/**
 * This class implements a node in an ID3 decision tree. It stores a RuleBase object for the node itself,
 * and CELLSTATES number of RuleBase objects for its children. It calculates (or inputs)
 * the feature in the rules with the most gain, and updates the RuleBase objects that will be copied to
 * each of its children. It also keeps a track of which features have been used so far, and which features
 * will be available for its children.
 */
class FixedTreeNode
{
private:
	int featureToCheck;				//!< \deprecated The feature of the rule base this node will check
	int remainingInstances;			//!< \deprecated The number of remaining instances that are not classified in this stage
	int classifiedInstances;		//!< \deprecated The number of instances that are classified after checking this feature
	RuleBase nodeRB;				//!< The rule base for this node to classify
	RuleBase childRB[CELLSTATES];	//!< The rule bases that this node will pass to its children
	decision nodeDecision;			//!< The decision a node makes on an instance, based on its rule base.

	/**
	 * The list of available features to check on. nodeFeatureUsed[i] = false means that
	 * the feature i has been used before and cannot be used here
	 */
	bool* nodeFeatureAvailable;

	/**
	 * The list of remaining features for children to pick from. It is shared between all the children.
	 */
	bool* childFeatureAvailable;

	/**
	 * The array of most important feature to the least important feature of the node's rule base.
	 */
	vector<int> mostGainArray;

	/**
	 * This function updates the childRBs, and is only called when featureToCheck is valid.
	 * is called only from updateChildRBs (void) or updateChildRBs (int featureIndex)
	 */
	void internal_updateChildRBs (void);

public:

	/**
	 * Returns the featureToChack data member.
	 */
	int getFeatureToCheck ();

	/**
	 * Sets the featureToCheck data member to the giver argument.
	 */
	void setFeatureToCheck(int);

	/**
	 * Returns the remainingInstances data member.
	 */
	int getRemainingInstances();

	/**
	 * Sets the remainingInstances data member to the giver argument.
	 */
	void setRemainingInstances(int);

	/**
	 * Returns the classifiedInstances data member.
	 */
	int getClassifiedInstances();

	/**
	 * Sets the classifiedInstances data member to the giver argument.
	 */
	void setClassifiedInstances(int);

	/**
	 * Sets the nodeRB data member to the giver argument.
	 */
	void setNodeRB (RuleBase newRB);

	/**
	 * creates the childRBs, each having the same feature value for the feature with most gain
	 * (stored in featureToCheck).
	 */
	void updateChildRBs (void);

	/**
	 * creates the childRBs, each having the same feature value for the feature whose index is given
	 */
	void updateChildRBs (int featureIndex);

	/**
	 * returns the index of the feature with the most gain.
	 */
	int featureWithMostGain();

	/**
	 * This function finds the best possible feature (i.e. the feature with the most gain
	 * and uses that to create childRBs. All the instances in a childRB will have the same
	 * value for the selected feature.
	 */
	void updateChildRBsBest ();

	/**
	 * This function uses the nodeFeatureAvailable[] to select the best "available" feature
	 * (i.e. nodeFeatureAvailable[i] = true and featureWithMostGain() = i) and uses that to
	 * create childRBs. All the instances in a childRB will have the same value for the selected feature.
	 */
	void updateChildRBBestAvailable();

	/**
	 * Returns the childRB rule base whose index is given.
	 */
	RuleBase getChildRB(int);

	/**
	 * Sets the nodeDecision of the node to the given value.
	 */
	void setNodeDecision(decision d);

	/**
	 * Returns the decision of the node.
	 */
	decision getNodeDecision (void);

	/**
	 * Initiates a node from a RuleBase object only. Since the node will be the root, other data members such as
	 * bestGainArray[] or nodeFeatureAvailable do not need any external information to form.
	 * \param rb The ruleBase object for which we are creating a decision tree.
	 */
	void setAsRoot (RuleBase& rb);

	/**
	 * Initiates a node from another node as its parent. Uses the parent's childRB and childFeatureAvailable.
	 * \param wichChild Tells which child (child 0, 1st, 2nd, etc) of the parent the calling node will be.
	 * \param parent Reference to the parent node, from which the calling node will be initiated.
	 */
	void updateFromParent (int whichChild, FixedTreeNode& parent);

	/** When creating an array of FixedTreeNodes, the default constructor is called for all of them.
	 * The default constructor does not create the dynamic arrays, so we call this function to create
	 * them first, and then start manipulating them. 
	 */
	void makeArraysOfBlankNode (int ruleSize);

	/** Assignment operator.*/
	FixedTreeNode& operator=(FixedTreeNode&);

	FixedTreeNode();
	FixedTreeNode(int feature, RuleBase& nrb);
	FixedTreeNode(FixedTreeNode& other);
	FixedTreeNode(RuleBase& rb);

	~FixedTreeNode();

};
